/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxinline.manager.pesquisar;

import br.com.foxinline.enums.Relatorios;
import br.com.foxinline.enums.TipoDocumento;
import br.com.foxinline.enums.TipoProcesso;
import br.com.foxinline.modelo.*;
import br.com.foxinline.servico.*;
import br.com.foxinline.util.Msg;
import br.com.foxinline.utilitarios.ArquivoUtilitario;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;

/**
 *
 * @author laverson
 */
@ViewScoped
@ManagedBean
public class ManagerPesquisarProtocolo implements Serializable {

    @EJB
    PessoaServico pessoaServico;
    @EJB
    ProtocoloServico protocoloServico;
    @EJB
    AnexoServico anexoServico;
    @EJB
    UsuarioServico usuarioServico;
    @EJB
    SecretariaServico secretariaServico;
    private Protocolo protocoloPesquisar;
    private Protocolo protocoloEditar;
    private Protocolo protocoloVisualizar;
    private Protocolo protocoloDelete;
    private List<Protocolo> protocolos;
    private Pessoa clientePesquisar;
    private Pessoa clienteEditar;
    private Pessoa clienteVisualizar;
    private Processo processoEditar;
    private List<Processo> processosEditar;
    private List<Processo> processosVisualizar;
    private List<Processo> processosRemover;
    private String eProtocolo;
    private String vProtocolo;
    private ArquivoUtilitario arquivoProtocolo = new ArquivoUtilitario();
    private static final String msgErroValidacao = ":: Erro de validação:";
    private static final String msgFailure = msgErroValidacao.concat(" o valor é necessário.");
    // Relatorio
    private Protocolo protocoloRelatorio;
    private List<Protocolo> protocoloRelatorios;
    private Date dataIni;
    private Date dataFim;
    private List<Processo> processoRelatorios;

    @PostConstruct
    public void init() {
        protocolos = protocoloServico.findLimit();
        protocoloPesquisar = new Protocolo();
        clientePesquisar = iniciarCliente();
        protocoloRelatorios = new ArrayList<Protocolo>();

        processosRemover = new ArrayList<Processo>();

        dataIni = new Date();
        dataFim = new Date();

        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        eProtocolo = params.get("eProtocolo");
        vProtocolo = params.get("vProtocolo");
        paramPost();
    }

    public void relatorio() {
        HashMap parametros = new HashMap();
        protocoloRelatorios = protocoloServico.pesquisarRelProtocolo(dataIni, dataFim);

        RelatorioServico.genReport(parametros, protocoloRelatorios, Relatorios.PROCESSO);
    }

    public void paramPost() {
        try {
            if (eProtocolo != null) {
                processoEditar = iniciarProcesso();
                protocoloEditar = protocoloServico.pesquisar(Long.parseLong(eProtocolo));
                processosEditar = protocoloEditar.getProcessos() != null ? protocoloEditar.getProcessos() : new ArrayList<Processo>();
                clienteEditar = protocoloEditar.getCliente() != null ? protocoloEditar.getCliente() : iniciarCliente();
            }
            if (vProtocolo != null) {
                protocoloVisualizar = protocoloServico.pesquisar(Long.parseLong(vProtocolo));
                processosVisualizar = protocoloVisualizar.getProcessos();
                clienteVisualizar = protocoloVisualizar.getCliente() != null ? protocoloVisualizar.getCliente() : new Pessoa();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void pesquisar() {
        protocoloPesquisar.setCliente(clientePesquisar);
        protocolos = protocoloServico.pesquisar(protocoloPesquisar);
    }

    public void atualizar() {
        try {
            if (protocoloValido()) {
                arquivoProtocolo.gravarAnexosDoProcesso(processosEditar);
                excluirAnexosProcessoRemovidos(processosRemover);

                protocoloEditar.setProcessos(processosEditar);
                protocoloEditar.setCliente(clienteEditar);
                protocoloServico.atualizar(protocoloEditar);
                Msg.messagemInfo(Msg.SuccessFull);
            } else {
                RequestContext.getCurrentInstance().execute("requiredCredor(true)");
            }
        } catch (EJBException e) {
            Exception causedByException = e.getCausedByException();
            if (!(causedByException instanceof javax.validation.ConstraintViolationException)) {
                Msg.messagemWarn("Número".concat(msgErroValidacao).concat(" número do protocolo já existe"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            Msg.messagemError(Msg.Failure);
        }
    }

    public void deletar() {
        try {
            protocoloServico.remover(protocoloDelete);
            protocolos.remove(protocoloDelete);
            Msg.messagemInfo(Msg.SuccessFull);
        } catch (Exception e) {
            e.printStackTrace();
            Msg.messagemError(Msg.Failure);
        }
    }

    public void existeCliente() {
        Pessoa p = pessoaServico.existProprietario(clienteEditar);

        if (p != null) {
            clienteEditar = p;
        } else {
            clienteEditar.setId(null);
        }
    }

    public List<SelectItem> getTipoDocumento() {
        List<SelectItem> items = new ArrayList<SelectItem>();
        for (TipoDocumento tipo : TipoDocumento.values()) {
            items.add(new SelectItem(tipo, tipo.getNome()));
        }
        return items;
    }

    public List<SelectItem> getTipoProcesso() {
        List<SelectItem> items = new ArrayList<SelectItem>();
        for (TipoProcesso tipo : TipoProcesso.values()) {
            items.add(new SelectItem(tipo, tipo.getNome()));
        }
        return items;
    }
    private static int tamanhoMaximoNome = 10;

    public String nomeAnexo(Anexo a) {
        if (a.getNomeExibicao().length() >= tamanhoMaximoNome) {
            return a.getNomeExibicao().substring(0, tamanhoMaximoNome).concat("...");
        }
        return a.getNomeExibicao().replace(".png", "").replace(" ", "_");
    }

    public String nomeAnexoPdf(Anexo a) {
        if (a.getNomeExibicao().length() >= tamanhoMaximoNome) {
            return a.getNomeExibicao().substring(0, tamanhoMaximoNome).concat("...");
        }
        return a.getNomeExibicao().replace(".pdf", "").replace(" ", "_");
    }

    public void handleAnnex(FileUploadEvent event) throws IOException {
        try {
            processoEditar.getAnexos().add(arquivoProtocolo.adicionarArquivo(event));
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ManagerPesquisarProtocolo.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            Logger.getLogger(ManagerPesquisarProtocolo.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     *
     * Remove o anexo da lista de anexos do processo que está sendo adicionado e
     * remove o arquivo do diretório que foi gravado
     *
     * @param anexo
     */
    public void removerAnexo(Anexo anexo) {
        try {
            arquivoProtocolo.excluirArquivo(new File(anexo.getUrl() + anexo.getNome()));
            processoEditar.getAnexos().remove(anexo);
        } catch (Exception e) {
            Msg.messagemError(Msg.Failure);
        }
    }

    /**
     *
     * Remove os anexos dos processos removidos da lista de processos do
     * protocolo
     *
     * @param processosLista
     */
    private void excluirAnexosProcessoRemovidos(List<Processo> processosLista) {
        for (Processo p : processosLista) {
            for (Anexo a : p.getAnexos()) {
                removerAnexo(a);
            }
        }
    }

    public void adicionarProcesso() {
        if (processoValido()) {
            if (!processosEditar.contains(processoEditar)) {
                processosEditar.add(processoEditar);
            }
            processoEditar = iniciarProcesso();
        } else {
            RequestContext.getCurrentInstance().execute("required(true)");
        }
    }

    public void editarProcesso(Processo p) {
        processoEditar = p;
        processosEditar.remove(p);
    }

    public void removerProcesso(Processo p) {
        processosRemover.add(p);
        processosEditar.remove(p);
    }

    private boolean processoValido() {

        if (isProcessoRequerimento() || isProcessoReciboPagamento()) {
            if (processoEditar.getObjeto() == null || processoEditar.getObjeto().equals("")) {
                Msg.messagemError("Objeto".concat(msgFailure));
                return false;
            }
        }
        if (isProcessoAutorizacao()) {
            if (processoEditar.getNumeroProcessoAdministrativo() == null) {
                Msg.messagemError("Nº Processo Administrativo".concat(msgFailure));
            }
            if (processoEditar.getNumeroServico() == null) {
                Msg.messagemError("Nº Serviço".concat(msgFailure));
            }
            if (processoEditar.getNumeroRequisicao() == null) {
                Msg.messagemError("Nº Requisição".concat(msgFailure));
            }
            if (processoEditar.getNumeroProcessoAdministrativo() == null || processoEditar.getNumeroServico() == null || processoEditar.getNumeroRequisicao() == null) {
                return false;
            }
        }
        if (isProcessoEmpenho()) {
            if (processoEditar.getNumeroNotaEmpenho() == null) {
                Msg.messagemError("Nota de Empenho".concat(msgFailure));
                return false;
            }
        }
        if (isProcessoNotaLiquidacao() || isProcessoPagamento()) {
            if (processoEditar.getValorLiquidacao() == null) {
                Msg.messagemError("Valor".concat(msgFailure));
                return false;
            }
        }
        return true;
    }

    private boolean protocoloValido() {
        if (isPessoaFisica()) {
            if (clienteEditar.getCpf() == null || clienteEditar.getCpf().equals("")) {
                Msg.messagemError("CPF".concat(msgFailure));
            }
            if (clienteEditar.getNome() == null || clienteEditar.getNome().equals("")) {
                Msg.messagemError("Nome".concat(msgFailure));
            }
            if ((clienteEditar.getCpf() == null || clienteEditar.getCpf().equals("")) || (clienteEditar.getNome() == null || clienteEditar.getNome().equals(""))) {
                return false;
            }
        } else {
            if (clienteEditar.getCnpj() == null || clienteEditar.getCnpj().equals("")) {
                Msg.messagemError("CPF".concat(msgFailure));
            }
            if (clienteEditar.getNomeFantasia() == null || clienteEditar.getNomeFantasia().equals("")) {
                Msg.messagemError("Nome".concat(msgFailure));
            }
            if ((clienteEditar.getCnpj() == null || clienteEditar.getCnpj().equals("")) || (clienteEditar.getNomeFantasia() == null || clienteEditar.getNomeFantasia().equals(""))) {
                return false;
            }
        }
        return true;
    }

    public Pessoa iniciarCliente() {
        Pessoa cliente = new Pessoa();
        cliente.setTipoDocumento(TipoDocumento.CPF);
        return cliente;
    }

    public Processo iniciarProcesso() {
        Processo processo = new Processo();
        processo.setAnexos(new ArrayList<Anexo>());
        processo.setTipoProcesso(TipoProcesso.REQUERIMENTO);
        return processo;
    }

    /**
     * Verifica se o protocolo pode ser completamente editado ou apenas os
     * trâmites
     *
     * @return true, caso seja possível, false caso contrário
     */
    public boolean habilitarEdicao() {
        Usuario usuarioAtual = usuarioServico.getCurrentUser();

        if (usuarioAtual.getId() >= 6L) {
//            if (usuarioAtual.getId() == protocoloEditar.getUsuario().getId()) {
            Secretaria secretaria = protocoloEditar.getTramites().get(protocoloEditar.getTramites().size() - 1).getSecretaria();
            if (secretaria.getId() == secretariaServico.find(usuarioAtual.getSetor()).getId()) {
                return false;
            }
//            }
        }

        return true;
    }

    public String numeroProtocolo() {

        if (protocoloVisualizar != null) {
            return numeroProtocolo(protocoloVisualizar.getNumero());
        }

        return null;
    }

    public String numeroProtocolo(Integer numeroProtocolo) {
        String numero = String.valueOf(numeroProtocolo);
        String ano = numero.substring(numero.length() - 4);
        numero = numero.substring(0, numero.length() - 4);
        return String.format("%05d", Integer.parseInt(numero)).concat("/").concat(ano);
    }

    public boolean isPessoaFisica() {
        if (eProtocolo != null) {
            return clienteEditar.getTipoDocumento().equals(TipoDocumento.CPF);
        }
        return clienteVisualizar.getTipoDocumento().equals(TipoDocumento.CPF);
    }

    public boolean isPessoaFisicaPesquisar() {
        return clientePesquisar.getTipoDocumento().equals(TipoDocumento.CPF);
    }

    public boolean isProcessoRequerimento() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.REQUERIMENTO);
    }

    public boolean isProcessoAutorizacao() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.AUTORIZACAO_COMPRA_SERVICO);
    }

    public boolean isProcessoEmpenho() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.EMPENHO);
    }

    public boolean isProcessoReciboPagamento() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.RECIBO_PAGAMENTO);
    }

    public boolean isProcessoNotaLiquidacao() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.NOTA_LIQUIDACAO);
    }

    public boolean isProcessoComprovante() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.COMPROVANTE_TRANSFERENCIA);
    }

    public boolean isProcessoPagamento() {
        return processoEditar.getTipoProcesso().equals(TipoProcesso.PAGAMENTO_BAIXA);
    }

    public Protocolo getProtocoloPesquisar() {
        return protocoloPesquisar;
    }

    public void setProtocoloPesquisar(Protocolo protocoloPesquisar) {
        this.protocoloPesquisar = protocoloPesquisar;
    }

    public Protocolo getProtocoloEditar() {
        return protocoloEditar;
    }

    public void setProtocolo(Protocolo protocolo) {
        this.protocoloEditar = protocolo;
    }

    public Protocolo getProtocoloVisualizar() {
        return protocoloVisualizar;
    }

    public void setProtocoloVisualizar(Protocolo protocoloVisualizar) {
        this.protocoloVisualizar = protocoloVisualizar;
    }

    public Protocolo getProtocoloDelete() {
        return protocoloDelete;
    }

    public void setProtocoloDelete(Protocolo protocoloDelete) {
        this.protocoloDelete = protocoloDelete;
    }

    public List<Protocolo> getProtocolos() {
        return protocolos;
    }

    public void setProtocolos(List<Protocolo> protocolos) {
        this.protocolos = protocolos;
    }

    public Pessoa getClientePesquisar() {
        return clientePesquisar;
    }

    public void setClientePesquisar(Pessoa clientePesquisar) {
        this.clientePesquisar = clientePesquisar;
    }

    public Pessoa getClienteEditar() {
        return clienteEditar;
    }

    public void setCliente(Pessoa cliente) {
        this.clienteEditar = cliente;
    }

    public Pessoa getClienteVisualizar() {
        return clienteVisualizar;
    }

    public void setClienteVisualizar(Pessoa clienteVisualizar) {
        this.clienteVisualizar = clienteVisualizar;
    }

    public Processo getProcessoEditar() {
        return processoEditar;
    }

    public void setProcesso(Processo processo) {
        this.processoEditar = processo;
    }

    public List<Processo> getProcessosEditar() {
        return processosEditar;
    }

    public void setProcessosEditar(List<Processo> processos) {
        this.processosEditar = processos;
    }

    public List<Processo> getProcessosVisualizar() {
        return processosVisualizar;
    }

    public void setProcessosVisualizar(List<Processo> processosVisualizar) {
        this.processosVisualizar = processosVisualizar;
    }

    public List<Processo> getProcessosRemover() {
        return processosRemover;
    }

    public void setProcessosRemover(List<Processo> processosRemover) {
        this.processosRemover = processosRemover;
    }

    public void visualizarDocs() {
        anexoServico.genReportAnnex(protocoloVisualizar);
    }

    public Date getDataIni() {
        return dataIni;
    }

    public void setDataIni(Date dataIni) {
        this.dataIni = dataIni;
    }

    public Date getDataFim() {
        return dataFim;
    }

    public void setDataFim(Date dataFim) {
        this.dataFim = dataFim;
    }
}
